home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / ADA / GNAT / !gcc / adainc / 4 / adb / s-fatgen < prev    next >
Text File  |  1996-02-12  |  20KB  |  717 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                       S Y S T E M . F A T _ G E N                        --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.7 $                              --
  10. --                                                                          --
  11. --     Copyright (C) 1992,1993,1994,1995 Free Software Foundation, Inc.     --
  12. --                                                                          --
  13. -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  14. -- terms of the  GNU General Public License as published  by the Free Soft- --
  15. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  16. -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  17. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  18. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  19. -- for  more details.  You should have  received  a copy of the GNU General --
  20. -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
  21. -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
  22. -- MA 02111-1307, USA.                                                      --
  23. --                                                                          --
  24. -- As a special exception,  if other files  instantiate  generics from this --
  25. -- unit, or you link  this unit with other files  to produce an executable, --
  26. -- this  unit  does not  by itself cause  the resulting  executable  to  be --
  27. -- covered  by the  GNU  General  Public  License.  This exception does not --
  28. -- however invalidate  any other reasons why  the executable file  might be --
  29. -- covered by the  GNU Public License.                                      --
  30. --                                                                          --
  31. -- GNAT was originally developed  by the GNAT team at  New York University. --
  32. -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
  33. --                                                                          --
  34. ------------------------------------------------------------------------------
  35.  
  36. --  The implementation here is portable to any IEEE implementation. It does
  37. --  not handle non-binary radix, and also assumes that model numbers and
  38. --  machine numbers are basically identical, which is not true of all possible
  39. --  floating-point implementations. On a non-IEEE machine, this body must be
  40. --  specialized appropriately, or better still, its generic instantiations
  41. --  should be replaced by efficient machine-specific code.
  42.  
  43. package body System.Fat_Gen is
  44.  
  45.    Float_Radix        : constant T := T (T'Machine_Radix);
  46.    Float_Radix_Inv    : constant T := 1.0 / Float_Radix;
  47.    Radix_To_M_Minus_1 : constant T := Float_Radix ** (T'Machine_Mantissa - 1);
  48.  
  49.    pragma Assert (T'Machine_Radix = 2);
  50.    --  This version does not handle radix 16
  51.  
  52.    --  Constants for Decompose and Scaling
  53.  
  54.    Rad    : constant T := T (T'Machine_Radix);
  55.    Invrad : constant T := 1.0 / Rad;
  56.  
  57.    subtype Expbits is Integer range 0 .. 6;
  58.    --  2 ** (2 ** 7) might overflow.  how big can radix-16 exponents get?
  59.  
  60.    Log_Power : constant array (Expbits) of Integer := (1, 2, 4, 8, 16, 32, 64);
  61.  
  62.    R_Power : constant array (Expbits) of T :=
  63.      (Rad **  1,
  64.       Rad **  2,
  65.       Rad **  4,
  66.       Rad **  8,
  67.       Rad ** 16,
  68.       Rad ** 32,
  69.       Rad ** 64);
  70.  
  71.    R_Neg_Power : constant array (Expbits) of T :=
  72.       (Invrad **  1,
  73.        Invrad **  2,
  74.        Invrad **  4,
  75.        Invrad **  8,
  76.        Invrad ** 16,
  77.        Invrad ** 32,
  78.        Invrad ** 64);
  79.  
  80.    -----------------------
  81.    -- Local Subprograms --
  82.    -----------------------
  83.  
  84.    procedure Decompose (XX : T; Frac : out T; Expo : out UI);
  85.    --  Decomposes a floating-point number into fraction and exponent parts
  86.  
  87.    --------------
  88.    -- Adjacent --
  89.    --------------
  90.  
  91.    function Adjacent (X, Towards : T) return T is
  92.    begin
  93.       if Towards = X then
  94.          return X;
  95.  
  96.       elsif Towards > X then
  97.          return Succ (X);
  98.  
  99.       else
  100.          return Pred (X);
  101.       end if;
  102.    end Adjacent;
  103.  
  104.    -------------
  105.    -- Ceiling --
  106.    -------------
  107.  
  108.    function Ceiling (X : T) return T is
  109.       XT : constant T := Truncation (X);
  110.  
  111.    begin
  112.       if X <= 0.0 then
  113.          return XT;
  114.  
  115.       elsif X = XT then
  116.          return X;
  117.  
  118.       else
  119.          return XT + 1.0;
  120.       end if;
  121.    end Ceiling;
  122.  
  123.    -------------
  124.    -- Compose --
  125.    -------------
  126.  
  127.    function Compose (Fraction : T; Exponent : UI) return T is
  128.       Arg_Frac : T;
  129.       Arg_Exp  : UI;
  130.  
  131.    begin
  132.       Decompose (Fraction, Arg_Frac, Arg_Exp);
  133.       return Scaling (Arg_Frac, Exponent);
  134.    end Compose;
  135.  
  136.    ---------------
  137.    -- Copy_Sign --
  138.    ---------------
  139.  
  140.    --  Configuration requirement: If this unit is used to implement the
  141.    --  floating-point attributes, then if Signed_Zeros is true, we must
  142.    --  have Machine_Overflows False, and we must generate infinities for
  143.    --  overflow (otherwise we can't implement signed zeroes properly).
  144.  
  145.    function Copy_Sign (Value, Sign : T) return T is
  146.       Result : T;
  147.  
  148.    begin
  149.       Result := abs Value;
  150.  
  151.       --  If we have signed zeroes true, then we know that machine overflows
  152.       --  is false, and that infinities are generated for overflow, so we can
  153.       --  test for minus zero by looking at the sign of the corresponding
  154.       --  infinity value (neat trick eh?)
  155.  
  156.       if Sign = 0.0 and then T'Signed_Zeros then
  157.          if 1.0 / Sign > 0.0 then
  158.             return Result;
  159.          else
  160.             return -Result;
  161.          end if;
  162.       end if;
  163.  
  164.       --  Handle non-zero cases, and also the zero case if signed zeroes
  165.       --  is false. In the latter case we always treat zero as positive.
  166.  
  167.       if Sign >= 0.0 then
  168.          return Result;
  169.       else
  170.          return -Result;
  171.       end if;
  172.    end Copy_Sign;
  173.  
  174.    ---------------
  175.    -- Decompose --
  176.    ---------------
  177.  
  178.    procedure Decompose (XX : T; Frac : out T; Expo : out UI) is
  179.       X : T := T'Machine (XX);
  180.  
  181.    begin
  182.       if X = 0.0 then
  183.          Frac := X;
  184.          Expo := 0;
  185.  
  186.          --  More useful would be defining Expo to be T'Machine_Emin - 1 or
  187.          --  T'Machine_Emin - T'Machine_Mantissa, which would preserve
  188.          --  monotonicity of the exponent fuction ???
  189.  
  190.       --  Check for infinities, transfinites, whatnot.
  191.  
  192.       elsif X > T'Safe_Last then
  193.          Frac := Invrad;
  194.          Expo := T'Machine_Emax + 1;
  195.  
  196.       elsif X < T'Safe_First then
  197.          Frac := -Invrad;
  198.          Expo := T'Machine_Emax + 2;    -- how many extra negative values?
  199.  
  200.       else
  201.          --  Case of nonzero finite x. Essentially, we just multiply
  202.          --  by Rad ** (+-2**N) to reduce the range.
  203.  
  204.          declare
  205.             Ax : T  := abs X;
  206.             Ex : UI := 0;
  207.  
  208.          --  Ax * Rad ** Ex is invariant.
  209.  
  210.          begin
  211.             if Ax >= 1.0 then
  212.                while Ax >= R_Power (Expbits'Last) loop
  213.                   Ax := Ax * R_Neg_Power (Expbits'Last);
  214.                   Ex := Ex + Log_Power (Expbits'Last);
  215.                end loop;
  216.  
  217.                --  Ax < Rad ** 64
  218.  
  219.                for N in reverse Expbits'First .. Expbits'Last - 1 loop
  220.                   if Ax >= R_Power (N) then
  221.                      Ax := Ax * R_Neg_Power (N);
  222.                      Ex := Ex + Log_Power (N);
  223.                   end if;
  224.  
  225.                   --  Ax < R_Power (N)
  226.                end loop;
  227.  
  228.                --  1 <= Ax < Rad
  229.  
  230.                Ax := Ax * Invrad;
  231.                Ex := Ex + 1;
  232.  
  233.             else
  234.                --  0 < ax < 1
  235.  
  236.                while Ax < R_Neg_Power (Expbits'Last) loop
  237.                   Ax := Ax * R_Power (Expbits'Last);
  238.                   Ex := Ex - Log_Power (Expbits'Last);
  239.                end loop;
  240.  
  241.                --  Rad ** -64 <= Ax < 1
  242.  
  243.                for N in reverse Expbits'First .. Expbits'Last - 1 loop
  244.                   if Ax < R_Neg_Power (N) then
  245.                      Ax := Ax * R_Power (N);
  246.                      Ex := Ex - Log_Power (N);
  247.                   end if;
  248.  
  249.                   --  R_Neg_Power (N) <= Ax < 1
  250.                end loop;
  251.             end if;
  252.  
  253.             if X > 0.0 then
  254.                Frac := Ax;
  255.             else
  256.                Frac := -Ax;
  257.             end if;
  258.  
  259.             Expo := Ex;
  260.          end;
  261.       end if;
  262.    end Decompose;
  263.  
  264.    --------------
  265.    -- Exponent --
  266.    --------------
  267.  
  268.    function Exponent (X : T) return UI is
  269.       X_Frac : T;
  270.       X_Exp  : UI;
  271.  
  272.    begin
  273.       Decompose (X, X_Frac, X_Exp);
  274.       return X_Exp;
  275.    end Exponent;
  276.  
  277.    -----------
  278.    -- Floor --
  279.    -----------
  280.  
  281.    function Floor (X : T) return T is
  282.       XT : constant T := Truncation (X);
  283.  
  284.    begin
  285.       if X >= 0.0 then
  286.          return XT;
  287.  
  288.       elsif XT = X then
  289.          return X;
  290.  
  291.       else
  292.          return XT - 1.0;
  293.       end if;
  294.    end Floor;
  295.  
  296.    --------------
  297.    -- Fraction --
  298.    --------------
  299.  
  300.    function Fraction (X : T) return T is
  301.       X_Frac : T;
  302.       X_Exp  : UI;
  303.  
  304.    begin
  305.       Decompose (X, X_Frac, X_Exp);
  306.       return X_Frac;
  307.    end Fraction;
  308.  
  309.    ------------------
  310.    -- Leading_Part --
  311.    ------------------
  312.  
  313.    function Leading_Part (X : T; Radix_Digits : UI) return T is
  314.       L    : UI;
  315.       Y, Z : T;
  316.  
  317.    begin
  318.       if Radix_Digits >= T'Machine_Mantissa then
  319.          return X;
  320.  
  321.       else
  322.          L := Exponent (X) - Radix_Digits;
  323.          Y := Truncation (Scaling (X, -L));
  324.          Z := Scaling (Y, L);
  325.          return Z;
  326.       end if;
  327.  
  328.    end Leading_Part;
  329.  
  330.    -------------
  331.    -- Machine --
  332.    -------------
  333.  
  334.    --  The trick with Machine is to force the compiler to store the result
  335.    --  in memory so that we do not have extra precision used. The compiler
  336.    --  is clever, so we have to outwit its possible optimizations!
  337.  
  338.    --  This is achieved by using the following array. In fact only the first
  339.    --  element is used, and Machine_Index is always 1, but we make sure the
  340.    --  compiler can't figure this out.
  341.  
  342.    Machine_Array : array (1 .. 2) of T;
  343.    Machine_Index : Integer;
  344.  
  345.    function Machine (X : T) return T is
  346.    begin
  347.       Machine_Array (1) := X;
  348.       return Machine_Array (Machine_Index);
  349.    end Machine;
  350.  
  351.    -----------
  352.    -- Model --
  353.    -----------
  354.  
  355.    --  We treat Model as identical to Machine. This is true of IEEE and other
  356.    --  nice floating-point systems, but not necessarily true of all systems.
  357.  
  358.    function Model (X : T) return T is
  359.    begin
  360.       return Machine (X);
  361.    end Model;
  362.  
  363.    ----------
  364.    -- Pred --
  365.    ----------
  366.  
  367.    --  Subtract from the given number a number equivalent to the value of its
  368.    --  least significant bit. Given that the most significant bit represents
  369.    --  a value of 1.0 * radix ** (exp - 1), the value we want is obtained by
  370.    --  shifting this by (mantissa-1) bits to the right, i.e. decreasing the
  371.    --  exponent by that amount.
  372.  
  373.    --  Zero has to be treated specially, since its exponent is zero
  374.  
  375.    function Pred (X : T) return T is
  376.       X_Frac : T;
  377.       X_Exp  : UI;
  378.  
  379.    begin
  380.       if X = 0.0 then
  381.          return -Succ (X);
  382.  
  383.       else
  384.          Decompose (X, X_Frac, X_Exp);
  385.  
  386.          --  A special case, if the number we had was a positive power of
  387.          --  two, then we want to subtract half of what we would otherwise
  388.          --  subtract, since the exponent is going to be reduced.
  389.  
  390.          if X_Frac = 0.5 and then X > 0.0 then
  391.             return X - Scaling (1.0, X_Exp - T'Machine_Mantissa - 1);
  392.  
  393.          --  Otherwise the exponent stays the same
  394.  
  395.          else
  396.             return X - Scaling (1.0, X_Exp - T'Machine_Mantissa);
  397.          end if;
  398.       end if;
  399.    end Pred;
  400.  
  401.    ---------------
  402.    -- Remainder --
  403.    ---------------
  404.  
  405.    function Remainder (X, Y : T) return T is
  406.       A        : T;
  407.       B        : T;
  408.       Arg      : T;
  409.       P        : T;
  410.       Arg_Frac : T;
  411.       P_Frac   : T;
  412.       Sign_X   : T;
  413.       IEEE_Rem : T;
  414.       Arg_Exp  : UI;
  415.       P_Exp    : UI;
  416.       K        : UI;
  417.       P_Even   : Boolean;
  418.  
  419.    begin
  420.       if X > 0.0 then
  421.          Sign_X :=  1.0;
  422.       else
  423.          Sign_X := -1.0;
  424.       end if;
  425.  
  426.       Arg := abs X;
  427.       P   := abs Y;
  428.  
  429.       if Arg < P then
  430.          P_Even := True;
  431.          IEEE_Rem := Arg;
  432.          P_Exp := Exponent (P);
  433.  
  434.       else
  435.          Decompose (Arg, Arg_Frac, Arg_Exp);
  436.          Decompose (P,   P_Frac,   P_Exp);
  437.  
  438.          P := Compose (P_Frac, Arg_Exp);
  439.          K := UI (Arg_Exp) - UI (P_Exp);
  440.          P_Even := True;
  441.          IEEE_Rem := Arg;
  442.  
  443.          for Cnt in reverse 0 .. K loop
  444.             if IEEE_Rem >= P then
  445.                P_Even := False;
  446.                IEEE_Rem := IEEE_Rem - P;
  447.             else
  448.                P_Even := True;
  449.             end if;
  450.  
  451.             P := P * 0.5;
  452.          end loop;
  453.       end if;
  454.  
  455.       --  That completes the calculation of modulus remainder. The final
  456.       --  step is get the IEEE remainder. Here we need to compare Rem with
  457.       --  (abs Y) / 2. We must be careful of unrepresentable Y/2 value
  458.       --  caused by subnormal numbers
  459.  
  460.       if P_Exp >= 0 then
  461.          A := IEEE_Rem;
  462.          B := abs Y * 0.5;
  463.       else
  464.          A := IEEE_Rem * 2.0;
  465.          B := abs Y;
  466.       end if;
  467.  
  468.       if A > B or else (A = B and then not P_Even) then
  469.          IEEE_Rem := IEEE_Rem - abs Y;
  470.       end if;
  471.  
  472.       return Sign_X * IEEE_Rem;
  473.  
  474.    end Remainder;
  475.  
  476.    --------------
  477.    -- Rounding --
  478.    --------------
  479.  
  480.    function Rounding (X : T) return T is
  481.       Result : T;
  482.       Tail   : T;
  483.  
  484.    begin
  485.       Result := Truncation (abs X);
  486.       Tail   := abs X - Result;
  487.  
  488.       if Tail >= 0.5  then
  489.          Result := Result + 1.0;
  490.       end if;
  491.  
  492.       if X > 0.0 then
  493.          return Result;
  494.  
  495.       elsif X < 0.0 then
  496.          return -Result;
  497.  
  498.       --  For zero case, make sure sign of zero is preserved
  499.  
  500.       else
  501.          return X;
  502.       end if;
  503.  
  504.    end Rounding;
  505.  
  506.    -------------
  507.    -- Scaling --
  508.    -------------
  509.  
  510.    --  Return x * rad ** adjustment quickly,
  511.    --  or quietly underflow to zero, or overflow naturally.
  512.  
  513.    function Scaling (X : T; Adjustment : UI) return T is
  514.    begin
  515.       if X = 0.0 or else Adjustment = 0 then
  516.          return X;
  517.       end if;
  518.  
  519.       --  Nonzero x. essentially, just multiply repeatedly by Rad ** (+-2**n).
  520.  
  521.       declare
  522.          Y  : T  := X;
  523.          Ex : UI := Adjustment;
  524.  
  525.       --  Y * Rad ** Ex is invariant
  526.  
  527.       begin
  528.          if Ex < 0 then
  529.             while Ex <= -Log_Power (Expbits'Last) loop
  530.                Y := Y * R_Neg_Power (Expbits'Last);
  531.                Ex := Ex + Log_Power (Expbits'Last);
  532.             end loop;
  533.  
  534.             --  -64 < Ex <= 0
  535.  
  536.             for N in reverse Expbits'First .. Expbits'Last - 1 loop
  537.                if Ex <= -Log_Power (N) then
  538.                   Y := Y * R_Neg_Power (N);
  539.                   Ex := Ex + Log_Power (N);
  540.                end if;
  541.  
  542.                --  -Log_Power (N) < Ex <= 0
  543.             end loop;
  544.  
  545.             --  Ex = 0
  546.  
  547.          else
  548.             --  Ex >= 0
  549.  
  550.             while Ex >= Log_Power (Expbits'Last) loop
  551.                Y := Y * R_Power (Expbits'Last);
  552.                Ex := Ex - Log_Power (Expbits'Last);
  553.             end loop;
  554.  
  555.             --  0 <= Ex < 64
  556.  
  557.             for N in reverse Expbits'First .. Expbits'Last - 1 loop
  558.                if Ex >= Log_Power (N) then
  559.                   Y := Y * R_Power (N);
  560.                   Ex := Ex - Log_Power (N);
  561.                end if;
  562.  
  563.                --  0 <= Ex < Log_Power (N)
  564.             end loop;
  565.  
  566.             --  Ex = 0
  567.          end if;
  568.          return Y;
  569.       end;
  570.    end Scaling;
  571.  
  572.    ----------
  573.    -- Succ --
  574.    ----------
  575.  
  576.    --  Similar computation to that of Pred: find value of least significant
  577.    --  bit of given number, and add. Zero has to be treated specially since
  578.    --  the exponent can be zero, and also we want the smallest denormal if
  579.    --  denormals are supported.
  580.  
  581.    function Succ (X : T) return T is
  582.       X_Frac : T;
  583.       X_Exp  : UI;
  584.       X1, X2 : T;
  585.  
  586.    begin
  587.       if X = 0.0 then
  588.          X1 := 2.0 ** T'Machine_Emin;
  589.  
  590.          --  Following loop generates smallest denormal
  591.  
  592.          loop
  593.             X2 := T'Machine (X1 / 2.0);
  594.             exit when X2 = 0.0;
  595.             X1 := X2;
  596.          end loop;
  597.  
  598.          return X1;
  599.  
  600.       else
  601.          Decompose (X, X_Frac, X_Exp);
  602.  
  603.          --  A special case, if the number we had was a negative power of
  604.          --  two, then we want to add half of what we would otherwise add,
  605.          --  since the exponent is going to be reduced.
  606.  
  607.          if X_Frac = 0.5 and then X < 0.0 then
  608.             return X + Scaling (1.0, X_Exp - T'Machine_Mantissa - 1);
  609.  
  610.          --  Otherwise the exponent stays the same
  611.  
  612.          else
  613.             return X + Scaling (1.0, X_Exp - T'Machine_Mantissa);
  614.          end if;
  615.       end if;
  616.    end Succ;
  617.  
  618.    ----------------
  619.    -- Truncation --
  620.    ----------------
  621.  
  622.    --  The basic approach is to compute
  623.  
  624.    --    T'Machine (RM1 + N) - RM1.
  625.  
  626.    --  where N >= 0.0 and RM1 = radix ** (mantissa - 1)
  627.  
  628.    --  This works provided that the intermediate result (RM1 + N) does not
  629.    --  have extra precision (which is why we call Machine). When we compute
  630.    --  RM1 + N, the exponent of N will be normalized and the mantissa shifted
  631.    --  shifted appropriately so the lower order bits, which cannot contribute
  632.    --  to the integer part of N, fall off on the right. When we subtract RM1
  633.    --  again, the significant bits of N are shifted to the left, and what we
  634.    --  have is an integer, because only the first e bits are different from
  635.    --  zero (assuming binary radix here).
  636.  
  637.    function Truncation (X : T) return T is
  638.       Result : T;
  639.  
  640.    begin
  641.       Result := abs X;
  642.  
  643.       if Result >= Radix_To_M_Minus_1 then
  644.          return Machine (X);
  645.  
  646.       else
  647.          Result := Machine (Radix_To_M_Minus_1 + Result) - Radix_To_M_Minus_1;
  648.  
  649.          if Result > abs X  then
  650.             Result := Result - 1.0;
  651.          end if;
  652.  
  653.          if X > 0.0 then
  654.             return  Result;
  655.  
  656.          elsif X < 0.0 then
  657.             return -Result;
  658.  
  659.          --  For zero case, make sure sign of zero is preserved
  660.  
  661.          else
  662.             return X;
  663.          end if;
  664.       end if;
  665.  
  666.    end Truncation;
  667.  
  668.    -----------------------
  669.    -- Unbiased_Rounding --
  670.    -----------------------
  671.  
  672.    function Unbiased_Rounding (X : T) return T is
  673.       Abs_X  : constant T := abs X;
  674.       Result : T;
  675.       Tail   : T;
  676.  
  677.    begin
  678.       Result := Truncation (Abs_X);
  679.       Tail   := Abs_X - Result;
  680.  
  681.       if Tail > 0.5  then
  682.          Result := Result + 1.0;
  683.  
  684.       elsif Tail = 0.5 then
  685.          Result := 2.0 * Truncation ((Result / 2.0) + 0.5);
  686.       end if;
  687.  
  688.       if X > 0.0 then
  689.          return Result;
  690.  
  691.       elsif X < 0.0 then
  692.          return -Result;
  693.  
  694.       --  For zero case, make sure sign of zero is preserved
  695.  
  696.       else
  697.          return X;
  698.       end if;
  699.  
  700.    end Unbiased_Rounding;
  701.  
  702.    ----------------------------
  703.    -- Package Initialization --
  704.    ----------------------------
  705.  
  706. begin
  707.    --  Set Machine_Index to 1, but not in an obvious manner (see function
  708.    --  Machine to understand why we are behaving in this secretive manner)
  709.  
  710.    Machine_Index := 2 ** 3;
  711.  
  712.    for J in 1 .. 3 loop
  713.       Machine_Index := Machine_Index / 2;
  714.    end loop;
  715.  
  716. end System.Fat_Gen;
  717.